package com.ruoyi.system.xmlAbstract;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.ruoyi.system.xmlAbstract.dto.XmlNodeBuildDto;
import com.ruoyi.system.xmlAbstract.interfaces.operation.XmlOperationInterface;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.stream.Collectors;

/**
 * XML格式生成   抽象类
 * @author : anxinr
 * @date : 2023/1/11 16:44
 */
@Slf4j
public abstract class XmlGenerateAbstract implements XmlOperationInterface {
    /**xml树节结构*/
    public XmlNodeBuildDto xmlNodeBuild = new XmlNodeBuildDto() ;
    /**xml数据*/
    public StringBuilder xml = new StringBuilder() ;
    /**当前操作的  XML  结点对象*/
    public XmlNodeBuildDto currentXmlNode = xmlNodeBuild ;
    /**当前操作的  XML  对象*/
    public XmlNodeBuildDto rootXmlNode = xmlNodeBuild ;


    /**
     * 设置当前操作结点
     * 从当前结点的子结点中，通过codeName获取并且设置为当前操作的结点
     * 可以通过索引下标来选择进入那个子结点
     * @param xmlNodeCode
     * @throws Exception
     */
    @Override
    public void setCurrentNodeToChildNodeByNodeName(String xmlNodeCode, Integer index) throws Exception {
        if (CollectionUtil.isEmpty(this.currentXmlNode.getList())){
            throw new Exception("当前结点没有子节点！") ;
        }
        List<XmlNodeBuildDto> childNodeList = this.currentXmlNode.getList().stream().filter(c -> c.getXmlNode().equals(xmlNodeCode)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(childNodeList)){
            throw new Exception("当前结点没有该子节点！") ;
        }
        try {
            this.currentXmlNode = childNodeList.get(index) ;
        }catch (Exception e){
            throw new Exception("当前结点没有该子节点索引！") ;
        }
    }

    /**
     * 在当前结点生成子结点
     * 包含h5 参数
     * @param xmlNodeCode
     * @param xmlNodeData
     * @param param
     */
    @Override
    public void generateChildNode(String xmlNodeCode, String param , String xmlNodeData) {
        List<XmlNodeBuildDto> list = currentXmlNode.getList();
        list.add(new XmlNodeBuildDto(xmlNodeCode,param,xmlNodeData)) ;
    }

    /**
     * 设置h5头标签属性
     * @param param
     */
    @Override
    public void setCurrentNodeH5Param(String param) {
        this.currentXmlNode.setXmlH5NodeParam(param);
    }

    /**
     * 断言
     * 当前结点有子节点
     * @return boolean
     */
    @Override
    public abstract boolean hasCurrentNodeChild() ;

    /**
     * 在当前结点生成子结点
     * @param xmlNodeCode
     * @param xmlNodeData
     */
    @Override
    public abstract void generateChildNode(String xmlNodeCode, String xmlNodeData) ;

    /**
     * 在当前结点生成子结点
     * @param xmlNodeCode
     */
    @Override
    public abstract void generateChildNode(String xmlNodeCode) ;

    /**
     * 生成根结点
     * @return boolean
     * @param xmlNodeCode
     */
    @Override
    public void generateRootNode(String xmlNodeCode){
        this.xmlNodeBuild.setXmlNode(xmlNodeCode);
    }

    /**
     * 切换当前结点到父节点
     * @throws Exception
     */
    @Override
    public abstract void changeCurrentNodeToParentNode() throws Exception;


    /**
     * 设置当前操作结点为根节点
     */
    @Override
    public void setCurrentNodeToRootNode(){
        this.currentXmlNode = this.rootXmlNode ;
    }

    /**
     * 设置当前操作结点
     * 从当前结点的子结点中，通过codeName获取并且设置为当前操作的结点
     * @param xmlNodeCode
     * @throws Exception
     */
    @Override
    public void setCurrentNodeToChildNodeByNodeName(String xmlNodeCode) throws Exception {
        if (CollectionUtil.isEmpty(this.currentXmlNode.getList())){
            throw new Exception("当前结点没有子节点！") ;
        }
        for (int i = 0; i < this.currentXmlNode.getList().size(); i++) {
            /**如果相等，则切换当前操作的xmlNode*/
            if (this.currentXmlNode.getList().get(i).getXmlNode().equals(xmlNodeCode)){
                this.currentXmlNode = this.currentXmlNode.getList().get(i) ;
                break;
            }
            /**如果循环结束没有结束循环，则当前结点没有该子结点*/
            if (i == (this.currentXmlNode.getList().size() - 1)){
                throw new Exception("当前结点没有子节点！") ;
            }
        }
    }

    /**
     * 移除当前结点
     */
    @Override
    public void removeCurrentNode() throws Exception {
        /**如果当前结点为根节点 则把数据都清空*/
        if (this.currentXmlNode.equals(this.rootXmlNode)){
            this.rootXmlNode.setList(null);
            this.rootXmlNode.setXmlNode(null);
            this.rootXmlNode.setXmlNodeData(null);
        }else {
            /**如果当前结点不为根结点，则返回到父结点，再操作删除*/
            this.changeCurrentNodeToParentNode();
            this.currentXmlNode.setList(null);
        }
    }

    /**
     * 删除当前结点的子结点
     * @param name
     */
    @Override
    public void removeChildNodeByName(String name) throws Exception {
        /**用 lambda表达式 来过滤结点，先判断这个结点是否存在*/
        if (StringUtils.isBlank(name)){
            throw new Exception("子结点name不能为空！") ;
        }
        if (this.currentXmlNode.getList().stream().noneMatch((item) -> (name.equals(item.getXmlNode())))) {
            /**如果不存在这个结点则不能删除*/
            throw new Exception("该子结点不存在!") ;
        }else {
            /**如果存在，则把name不同的元素过滤出来，这样就可以把该子结点删除*/
            this.currentXmlNode.setList(
                    this.currentXmlNode.getList().stream().filter((item)->(!name.equals(item.getXmlNode()))).collect(Collectors.toList())
            );
        }
    }


    /**
     * 递归遍历主结点  匹配数据
     */
    public boolean ergodicRootNodeForMatching(XmlNodeBuildDto data ,XmlNodeBuildDto currentNode , List<XmlNodeBuildDto> dataList){
        /**如果当前结点是主结点返回 true 不操作*/
        if (this.rootXmlNode.equals(data)){
            return true ;
        }
        /**如果当前结点为空 返回false*/
        if (CollectionUtil.isEmpty(dataList)){
            return false ;
        }
        if (dataList.contains(data)){
            this.currentXmlNode = currentNode ;
            return true ;
        }else {
            for (XmlNodeBuildDto childNode : dataList) {
                boolean result = ergodicRootNodeForMatching(data, childNode, childNode.getList());
                if (result) {
                    return true;
                }
            }
        }
//        for (XmlNodeBuildDto xmlNodeBuildDto : dataList) {
//            /**结点数组中包含当前结点 返回true */
//            if (xmlNodeBuildDto.equals(data)){
//
//            }else {
//                /**否则进入该结点的子结点查询是否匹配*/
//                if (CollectionUtil.isNotEmpty(xmlNodeBuildDto.getList())){
//                    boolean matchingResult = ergodicRootNodeForMatching(data, xmlNodeBuildDto.getList());
//                    /**如果匹配结果为true 则该结点是查询结点的父结点*/
//                    if (matchingResult){
//                        this.currentXmlNode = xmlNodeBuildDto ;
//                        return true ;
//                    }
//                }
//            }
//        }
        return false ;
    }



}
